package com.sqlcheck.controller;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.sqlcheck.common.response.ApiResponse;
import com.sqlcheck.dto.request.SqlStatementQueryDTO;
import com.sqlcheck.dto.response.*;
import com.sqlcheck.entity.ScanResult;
import com.sqlcheck.entity.SqlStatement;
import com.sqlcheck.repository.ScanResultRepository;
import com.sqlcheck.service.ScanTaskService;
import com.sqlcheck.service.SqlStatementService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Slf4j
@RestController
@RequestMapping("/api/sql-statements")
@RequiredArgsConstructor
public class SqlStatementController {

    private final SqlStatementService sqlStatementService;
    private final ScanTaskService scanTaskService;
    private final ScanResultRepository scanResultRepository;

    /**
     * 分页查询SQL语句清单
     */
    @GetMapping
    public ApiResponse<PageResult<SqlStatementVO>> getStatements(SqlStatementQueryDTO query) {
        IPage<SqlStatement> page = sqlStatementService.getStatements(query);

        PageResult<SqlStatementVO> result = PageResult.<SqlStatementVO>builder()
                .records(page.getRecords().stream().map(this::convertToVO).collect(Collectors.toList()))
                .total(page.getTotal())
                .current(page.getCurrent())
                .size(page.getSize())
                .build();

        return ApiResponse.success(result);
    }

    /**
     * 获取SQL语句详情
     */
    @GetMapping("/{taskId}/{statementNumber}")
    public ApiResponse<SqlStatementDetailVO> getStatementDetail(@PathVariable Long taskId,
            @PathVariable Integer statementNumber) {
        SqlStatement statement = sqlStatementService.getByTaskAndNumber(taskId, statementNumber);
        if (statement == null) {
            return ApiResponse.error("SQL语句不存在");
        }

        // 获取相关的分析结果
        List<ScanResult> issues = getByTaskAndStatementNumber(taskId, statementNumber);

        SqlStatementDetailVO detail = SqlStatementDetailVO.builder()
                .statement(convertToVO(statement))
                .issues(issues.stream().map(this::convertIssueToVO).collect(Collectors.toList()))
                .gitUrl(buildGitUrl(statement)) // 构建Git在线地址
                .build();

        return ApiResponse.success(detail);
    }

    /**
     * 获取任务的SQL统计信息
     */
    @GetMapping("/statistics/{taskId}")
    public ApiResponse<SqlStatisticsVO> getStatistics(@PathVariable Long taskId) {
        SqlStatisticsVO statistics = sqlStatementService.getStatistics(taskId);
        return ApiResponse.success(statistics);
    }

    /**
     * 查询涉及特定表的SQL语句
     */
    @GetMapping("/by-table/{tableName}")
    public ApiResponse<List<SqlStatementVO>> getStatementsByTable(@PathVariable String tableName) {
        List<SqlStatement> statements = sqlStatementService.getStatementsByTable(tableName);
        List<SqlStatementVO> vos = statements.stream()
                .map(this::convertToVO)
                .collect(Collectors.toList());
        return ApiResponse.success(vos);
    }

    /**
     * 关键词搜索SQL语句
     */
    @GetMapping("/search")
    public ApiResponse<List<SqlStatementVO>> searchStatements(@RequestParam Long taskId, @RequestParam String keyword) {
        List<SqlStatement> statements = sqlStatementService.searchStatements(taskId, keyword);
        List<SqlStatementVO> vos = statements.stream()
                .map(this::convertToVO)
                .collect(Collectors.toList());
        return ApiResponse.success(vos);
    }

    /**
     * 根据Java注解类型查询
     */
    @GetMapping("/java-annotation/{taskId}/{annotationType}")
    public ApiResponse<List<SqlStatementVO>> getStatementsByJavaAnnotationType(
            @PathVariable Long taskId,
            @PathVariable SqlStatement.JavaAnnotationType annotationType) {
        List<SqlStatement> statements = sqlStatementService.getStatementsByJavaAnnotationType(taskId, annotationType);
        List<SqlStatementVO> vos = statements.stream()
                .map(this::convertToVO)
                .collect(Collectors.toList());
        return ApiResponse.success(vos);
    }

    /**
     * 根据MyBatis XML元素类型查询
     */
    @GetMapping("/mybatis-xml/{taskId}/{xmlElement}")
    public ApiResponse<List<SqlStatementVO>> getStatementsByMybatisXmlElement(
            @PathVariable Long taskId,
            @PathVariable SqlStatement.MybatisXmlElement xmlElement) {
        List<SqlStatement> statements = sqlStatementService.getStatementsByMybatisXmlElement(taskId, xmlElement);
        List<SqlStatementVO> vos = statements.stream()
                .map(this::convertToVO)
                .collect(Collectors.toList());
        return ApiResponse.success(vos);
    }

    // Helper methods

    private List<ScanResult> getByTaskAndStatementNumber(Long taskId, Integer statementNumber) {
        QueryWrapper<ScanResult> wrapper = new QueryWrapper<>();
        wrapper.eq("task_id", taskId)
                .eq("statement_number", statementNumber);
        return scanResultRepository.selectList(wrapper);
    }

    private SqlStatementVO convertToVO(SqlStatement statement) {
        SqlStatementVO.SqlStatementVOBuilder builder = SqlStatementVO.builder()
                .taskId(statement.getTaskId())
                .statementNumber(statement.getStatementNumber())
                .sqlContent(statement.getContent())
                .sqlType(statement.getSqlType())
                .sourceType(statement.getSourceType())
                .isNativeQuery(statement.getIsNativeQuery());

        // 根据来源类型设置不同的字段
        if (statement.getSourceType() == SqlStatement.SourceType.DDL_SCRIPT) {
            // DDL相关字段
            builder.ddlType(statement.getDdlType())
                    .primaryTable(statement.getPrimaryTable())
                    .affectedTables(statement.getAffectedTables())
                    .databaseObjects(statement.getDatabaseObjects());
        } else {
            // Git源码相关字段
            builder.sourceFile(statement.getSourceFile())
                    .lineNumber(statement.getLineNumber())
                    .className(statement.getClassName())
                    .methodName(statement.getMethodName())
                    .javaAnnotationType(statement.getJavaAnnotationType())
                    .mybatisXmlElement(statement.getMybatisXmlElement())
                    .gitUrl(buildGitUrl(statement));
        }

        // 通用字段
        builder.extractionMetadata(statement.getExtractionMetadata());

        return builder.build();
    }

    private ScanResultVO convertIssueToVO(ScanResult issue) {
        return ScanResultVO.builder()
                .ruleId(issue.getRuleId())
                .ruleName(issue.getRuleName())
                .severity(issue.getSeverity() != null ? 
                    ScanResultVO.SeverityEnum.valueOf(issue.getSeverity().name()) : null)
                .description(issue.getIssueDescription())
                .suggestion(issue.getSuggestion())
                .originalSql(issue.getOriginalSql())
                .suggestedSql(issue.getSuggestedSql())
                .build();
    }

    private String buildGitUrl(SqlStatement statement) {
        try {
            // 根据任务配置和相对路径构建Git在线地址
            ScanTaskResponse taskResponse = scanTaskService.getTaskById(statement.getTaskId());
            if (taskResponse == null) {
                return null;
            }

            Map<String, Object> config = taskResponse.getConfig();
            if (config == null) {
                return null;
            }

            String repositoryUrl = (String) config.get("repositoryUrl");
            if (repositoryUrl == null) {
                repositoryUrl = (String) config.get("gitRepositoryUrl");
            }

            String branch = taskResponse.getBranchName();
            String relativePath = statement.getSourceFile();
            Integer lineNumber = statement.getLineNumber();

            if (repositoryUrl != null && relativePath != null && lineNumber != null) {
                // 处理不同Git平台的URL格式
                if (repositoryUrl.contains("gitlab")) {
                    return String.format("%s/-/blob/%s/%s#L%d",
                            repositoryUrl, branch, relativePath, lineNumber);
                } else if (repositoryUrl.contains("github")) {
                    return String.format("%s/blob/%s/%s#L%d",
                            repositoryUrl, branch, relativePath, lineNumber);
                } else if (repositoryUrl.contains("gitee")) {
                    return String.format("%s/blob/%s/%s#L%d",
                            repositoryUrl, branch, relativePath, lineNumber);
                }
            }
        } catch (Exception e) {
            log.warn("构建Git URL失败: statementId={}", statement.getId(), e);
        }

        return null;
    }
}